﻿using System.Windows;
using System.Windows.Controls;

namespace FluentTemplates
{
    public static class ControlExtensions
    {
        #region Public Static Methods

        /// <summary>
        /// Wraps the given object in a TemplatePart<typeparamref name="T"/>> class
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static TemplatePart<T> As<T>(this object obj) where T : DependencyObject
        {
            return new TemplatePart<T>(obj as T);
        }

        /// <summary>
        /// Wraps the given object in a TemplatePart<typeparamref name="T"/>> class
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="control"></param>
        /// <param name="templateName"></param>
        /// <returns></returns>
        public static TemplatePart<T> As<T>(this object obj, Control control, string templateName)
            where T : DependencyObject
        {
            return new TemplatePart<T>(obj as T, templateName, control);
        }

        /// <summary>
        /// Calls GetTemplatePartBinding and returns a TemplatePart<typeparamref name="T"/>> wrapping the resulting template part object
        /// </summary>
        /// <typeparam name="T">A dependancy property type for the template part</typeparam>
        /// <param name="control"></param>
        /// <param name="templateName">The name of the TemplatePart to retrieve</param>
        /// <returns></returns>
        public static TemplatePart<T> GetTemplateChild<T>(this ITemplatePartBinding control, string templateName)
            where T : DependencyObject
        {
            return new TemplatePart<T>(control.GetTemplatePartBinding(templateName) as T, templateName);
        }

        #endregion

        ///// <summary>
        ///// Throws and ArgumentException if the wrapped object is null
        ///// </summary>
        ///// <typeparam name="T"></typeparam>
        ///// <param name="obj"></param>
        ///// <returns></returns>
        //public static TemplatePart<T> Required<T>(this TemplatePart<T> obj) where T : DependencyObject
        //{
        //    return obj.Required(string.Empty);
        //}

        ///// <summary>
        ///// Throws an ArgumentException with the given message if the wrapped object is null
        ///// </summary>
        ///// <typeparam name="T"></typeparam>
        ///// <param name="obj"></param>
        ///// <param name="message"></param>
        ///// <returns></returns>
        //public static TemplatePart<T> Required<T>(this TemplatePart<T> obj, string message) where T : DependencyObject
        //{
        //    if (obj.Object == null)
        //        throw !string.IsNullOrWhiteSpace(message)
        //                  ? new ArgumentException(message)
        //                  : new ArgumentException(string.Format("The required Template Part was not assigned: {0}",
        //                                                        obj.TemplatePartName));

        //    return obj;
        //}
        ///// <summary>
        ///// Invokes supplied action with the wrapped object <typeparamref name="T"/>
        ///// </summary>
        ///// <typeparam name="T">the wrapped object type</typeparam>
        ///// <param name="obj"></param>
        ///// <param name="bindingExpression">The action to execute on the wrapped object</param>
        ///// <returns></returns>
        //public static TemplatePart<T> WireUp<T>(this TemplatePart<T> obj, Action<T> bindingExpression)
        //    where T : DependencyObject
        //{
        //    if(obj.Object!=null)
        //    bindingExpression(obj.Object);
        //    return obj;
        //}

        //public static object InvokeGetTemplateChild(this Control control, string templateName)
        //{
        //    try
        //    {
        //        return RunInstanceMethod(typeof(Control), "GetTemplateChild", control, new[] { templateName });
        //    }
        //    catch
        //    {
        //        return null;
        //    }
        //}

        //private static object RunInstanceMethod(Type t, string strMethod,
        //                                        object objInstance, object[] aobjParams)
        //{
        //    var eFlags = BindingFlags.Instance | BindingFlags.Public |
        //                 BindingFlags.NonPublic;
        //    return RunMethod(t, strMethod,
        //                     objInstance, aobjParams, eFlags);
        //}

        ////end of method

        //private static object RunMethod(Type t, string
        //                                            strMethod, object objInstance, object[] aobjParams,
        //                                BindingFlags eFlags)
        //{
        //    MethodInfo m;
        //    m = t.GetMethod(strMethod, eFlags);
        //    if (m == null)
        //        throw new ArgumentException("There is no method '" +
        //                                    strMethod + "' for type '" + t + "'.");
        //    var method = MethodBase.GetMethodFromHandle(m.MethodHandle);

        //    return method.Invoke(objInstance, aobjParams);
        //    var objRet = m.Invoke(objInstance, aobjParams);
        //    return objRet;
        //}

        //end of method
    }
}